//------------------------------------------------------------------------------
// Copyright (C) 2007-2008 Samuel Lacroix
// This file is part of Visual Local History 2005
// 
// Visual Local History 2005 is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the License,
// or (at your option) any later version.
// 
// Visual Local History 2005 is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Visual Local History 2005; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//------------------------------------------------------------------------------

#include "stdafx.h"
#include "HistoryWindow.h"
#include "Config.h"


// Called when needed, to update the "Enabled" state of the interface
void HistoryAddIn::HistoryWindow::UpdateEnabledButtons()
{
    // we don't rely on the interface to know if an action can be done, so this
    // method is just for ease of use (if all these lines are deleted, the
    // history window should still works perfectly)
    bool GotADoc = ApplicationObject->ActiveDocument != nullptr || connectObject->realCurrentDocument != nullptr;
    deleteButton->Enabled = GotADoc;
    deleteToolStripMenuItem->Enabled = deleteButton->Enabled;            
    restoreButton->Enabled = GotADoc && treeView->SelectedNode && treeView->SelectedNode->Level == 1;
    restoreToolStripMenuItem->Enabled = restoreButton->Enabled;            
    openButton->Enabled = GotADoc; 
    openToolStripMenuItem->Enabled = openButton->Enabled; 
    compareLatestButton->Enabled = treeView->SelectedNode && treeView->SelectedNode->Level == 1 && ConnectObject->config->DiffToolCommand->Trim()->Length > 0;
    compareLatestMenuItem->Enabled = compareLatestButton->Enabled;           
    compareActiveButton->Enabled = GotADoc && treeView->SelectedNode && treeView->SelectedNode->Level == 1 && ConnectObject->config->DiffToolCommand->Trim()->Length > 0;  
    compareActiveMenuItem->Enabled = compareActiveButton->Enabled;
    compareStripSplitButton->Enabled = compareLatestButton->Enabled || compareActiveButton->Enabled;            
    compareMenuItem->Enabled = compareStripSplitButton->Enabled;
}

// Open action : opens selected backup(s)
void HistoryAddIn::HistoryWindow::ActionOpen()
{
    TreeNode^ Selected = treeView->SelectedNode;
    if (Selected && ApplicationObject->ActiveDocument)
    {
        if (Selected->Level == 0)
        {
            // A day is selected
            if (Selected->Nodes->Count > 1)
            {
                if (DialogResult::No == MessageBox::Show("Do you wish to open all revisions of the selected day ?", "Open all revisions ?",  MessageBoxButtons::YesNo, MessageBoxIcon::Question))
                    return;
            }
            for each (TreeNode^ treeNode in Selected->Nodes)
            {
                OpenBackup((String^) treeNode->Tag, (String^) treeView->Tag);
            }
        }
        else if (treeView->SelectedNode->Level == 1)
        {
            OpenBackup((String^) Selected->Tag, (String^) treeView->Tag); 
        }
    }
}

// Restore action: restore the selected backup
void HistoryAddIn::HistoryWindow::ActionRestore()
{
    try
    {
        String^ CurrentRevisionFileName = (String^) treeView->Tag;
        if (treeView->SelectedNode && treeView->SelectedNode->Level == 1 && CurrentRevisionFileName)
        {
            String^ fileName = (String^) treeView->SelectedNode->Tag;            
            if (DialogResult::Yes == MessageBox::Show("Do you wish to overwrite the current revision of " + System::IO::Path::GetFileName(CurrentRevisionFileName) + " with the selected one ?", "Overwrite current revision ?",  MessageBoxButtons::YesNo, MessageBoxIcon::Question))
            {
                ApplicationObject->ItemOperations->OpenFile(CurrentRevisionFileName, Constants::vsViewKindAny);
                if (SelectedIsCurrent()) // check if the current activated window is the current version of the file we want to restore (we are going to erase text in the editor, so we have to be sure we won't erase something wrong)
                {
                    // erase text
                    TextDocument^ textDocument = (TextDocument^) ApplicationObject->ActiveDocument->Object("TextDocument");
                    EditPoint^ editPoint = textDocument->CreateEditPoint(nullptr);
                    editPoint->MoveToAbsoluteOffset(1);
                    editPoint->Delete(textDocument->EndPoint);
                    editPoint->InsertFromFile(fileName);
                    
                    // save (this creates another backup)
                    ApplicationObject->ActiveDocument->Save(ApplicationObject->ActiveDocument->FullName);
                }
            }
        }
    }
    catch (Exception^ e)
    {
        MessageBox::Show(e->Message, "Visual local History 2005", MessageBoxButtons::OK, MessageBoxIcon::Error);    	
    }
}

// Delete action: deletes selected backup(s)
void HistoryAddIn::HistoryWindow::ActionDelete()
{
    try
    {
        if (!ApplicationObject->ActiveDocument)
            return;

        TreeNode^ Selected = treeView->SelectedNode;
        if (Selected && Selected->Level == 0)
        {
            // A day is selected
            if (DialogResult::No == MessageBox::Show("Do you wish to delete all revisions of the selected day ?", "Delete all revisions ?",  MessageBoxButtons::YesNo, MessageBoxIcon::Question))
                return;
            for each (TreeNode^ treeNode in Selected->Nodes)
            {
                String^ fileName = (String^) treeNode->Tag;
                if (fileName)
                {
                    File::SetAttributes(fileName, File::GetAttributes(fileName) & ~FileAttributes::ReadOnly); 
                    File::Delete(fileName);
                }    
            }
            Selected->Remove();
        }
        else if (Selected && Selected->Level == 1)
        {
            // A single backup is selected
            String^ fileName = (String^) Selected->Tag;
            if (DialogResult::No == MessageBox::Show("Do you wish to delete the selected revision ?", "Delete selected revision ?",  MessageBoxButtons::YesNo, MessageBoxIcon::Question))
                return;
            try
            {
                File::SetAttributes(fileName, File::GetAttributes(fileName) & ~FileAttributes::ReadOnly); 
                File::Delete(fileName);
            }
            catch (...)
            {
            }
            if (Selected->Parent->Nodes->Count > 1)
                Selected->Remove();
            else
                Selected->Parent->Remove();
        }  
    }
    catch (Exception^ e)
    {
        MessageBox::Show(e->Message, "Visual local History 2005", MessageBoxButtons::OK, MessageBoxIcon::Error);	
    }
}

// Compare latest action: compare selected backup with current revision
void HistoryAddIn::HistoryWindow::ActionCompareLatest()
{
    TreeNode^ Selected = treeView->SelectedNode;
    try
    {
        if (Selected && Selected->Level == 1)
        {
            String^ CurrentFullName = (String^) treeView->Tag;
            String^ OldFullName = CreateTempFile((String^) Selected->Tag, CurrentFullName);
            
            String^ Command = ConnectObject->config->DiffToolCommand->Trim();
            String^ Args = ConnectObject->config->DiffToolArgs->Trim();
            
            Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::CurrentRevisionName, "\"" + System::IO::Path::GetFileName(CurrentFullName) + " (current version)" + "\"");
            Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::SelectedBackupName, "\"" + System::IO::Path::GetFileName(CurrentFullName) + " (old version)" + "\"");
            Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::CurrentRevision, "\"" + CurrentFullName + "\"");
            Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::SelectedBackup, "\"" + OldFullName + "\"");
            Args = Args->Trim();
            System::Diagnostics::Process^ proc = gcnew System::Diagnostics::Process;
            proc->EnableRaisingEvents = false;
            proc->StartInfo->FileName = Command;
            proc->StartInfo->Arguments = Args;
            proc->Start();
        }
    }
    catch (Exception^ e)
    {
    	MessageBox::Show("Unable to start the file comparison tool.\n" + e->Message, "Visual Local History 2005", MessageBoxButtons::OK, MessageBoxIcon::Error);
    }
}

// Compare active action: compare selected backup with active document
void HistoryAddIn::HistoryWindow::ActionCompareActive()
{
    TreeNode^ Selected = treeView->SelectedNode;
    try
    {
        if (Selected && ApplicationObject->ActiveDocument)
        {
            if (Selected->Level == 1)
            {
                String^ CurrentFullName = ApplicationObject->ActiveDocument->FullName;
                String^ OldFullName = CreateTempFile((String^) Selected->Tag, (String^) treeView->Tag);
                
                String^ Command = ConnectObject->config->DiffToolCommand->Trim();
                String^ Args = ConnectObject->config->DiffToolArgs->Trim();
                
                Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::CurrentRevisionName, "\"" + System::IO::Path::GetFileName(CurrentFullName) + " (opened version)\"");
                Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::SelectedBackupName, "\"" + System::IO::Path::GetFileName((String^) treeView->Tag) + " (old version)" + "\"");
                Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::CurrentRevision, "\"" + CurrentFullName + "\"");
                Args = Args->Replace(Connect::DiffToolArgsChar + Connect::DiffToolArgs::SelectedBackup, "\"" + OldFullName + "\"");
                Args = Args->Trim();
                System::Diagnostics::Process^ proc = gcnew System::Diagnostics::Process;
                proc->EnableRaisingEvents=false;
                proc->StartInfo->FileName = Command;
                proc->StartInfo->Arguments = Args;
                proc->Start();
            }
        }
    }
    catch (Exception^ e)
    {
    	MessageBox::Show("Unable to start the file comparison tool.\n" + e->Message, "Visual Local History 2005", MessageBoxButtons::OK, MessageBoxIcon::Error);
    }
}

// Called by ActionOpen to open a single backup
void HistoryAddIn::HistoryWindow::OpenBackup(String^ BackupPath, String^ FileSource)
{
    ApplicationObject->ItemOperations->OpenFile(CreateTempFile(BackupPath, FileSource), Constants::vsViewKindAny);
}

// Returns true if the selected backup corresponds to the current active document
// It's used to disable the ability to restore a file if the current file is not displayed (since 'restore' will erase the text in the editor)
bool HistoryAddIn::HistoryWindow::SelectedIsCurrent()
{
    try
    {
        Document^ RealCurrent = ConnectObject->realCurrentDocument != nullptr ? ConnectObject->realCurrentDocument : ApplicationObject->ActiveDocument;
        String^ RelativeFileName = Connect::DirRelativeDirTo(ApplicationObject->Solution->FullName, RealCurrent->FullName);
        String^ fileHistoryPath = connectObject->ReadValueFromLayoutFile(RelativeFileName);
        if (!fileHistoryPath || !connectObject->GetHistoryPath())
            return false;
        DirectoryInfo^ di = gcnew DirectoryInfo(connectObject->GetHistoryPath() + fileHistoryPath);
        if (!di->Exists)
            return false;
        if (Path::GetDirectoryName((String^) treeView->SelectedNode->Tag) != di->FullName)
            return false;
    }
    catch (Exception^)
    {
        return false;    	
    }
    return true;
}

String^ HistoryAddIn::HistoryWindow::CreateTempFile(String^ FileToCopy, String^ FileSource)
{
    String^ TempName = (String^) ConnectObject->BackupTempFiles[FileToCopy];
    if (TempName)
    {
        if (File::Exists(TempName))
        {
            String^ DataTemp = File::ReadAllText(TempName);
            String^ DataBackup = File::ReadAllText(FileToCopy);
            if (DataTemp != DataBackup)
            {
                TempName = nullptr;   
            }
        }
        else
        {
            TempName = nullptr;   
        }
    }
    if (!TempName)
    {
        do
        {
            #pragma push_macro("GetTempPath")
            #undef GetTempPath
            // We want the same extension, to activate the correct syntax highlighting, that's why we don't use GetTempFileName 
            TempName = System::IO::Path::GetTempPath() + Path::GetFileNameWithoutExtension(Path::GetRandomFileName()) + Path::GetExtension(FileSource);
            #pragma pop_macro("GetTempPath")
        } while (File::Exists(TempName));
        File::Copy(FileToCopy, TempName, true);
        File::SetAttributes(TempName, File::GetAttributes(TempName) & ~FileAttributes::ReadOnly | FileAttributes::Temporary);
        ConnectObject->TempFiles->Add(TempName);
        ConnectObject->BackupTempFiles[FileToCopy] = TempName;
        ConnectObject->BackupTempFileSources[TempName] = FileSource;
    }
    return TempName;
}